package com.portal.framework.searchform;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.Subcriteria;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;

import com.opensymphony.util.BeanUtils;
import com.portal.framework.common.CommonUtil;
import com.portal.framework.common.lang.ConstructorCaster;
import com.portal.framework.common.lang.NameValue;
import com.portal.framework.dao.annotation.PropertySearchProp;
import com.portal.framework.dao.annotation.PropertySearchType;
import com.portal.framework.dao.annotation.SearchProp;
import com.portal.framework.dao.annotation.SearchProps;
import com.portal.framework.dao.ISearchForm;
import com.portal.framework.dao.ProjectionSearchType;
import com.portal.framework.dao.SearchType;
import com.portal.framework.dao.ISearchForm.PropertyCondition;
import com.portal.framework.dao.ISearchForm.SearchCondition;
import com.portal.framework.dao.ISearchForm.SearchOrder;
import com.portal.framework.page.Pager;
import com.portal.framework.page.PagerResult;
import com.portal.framework.util.ClassUtil;
import com.portal.framework.util.CollectionUtils;
import com.portal.framework.util.NameList;
import com.portal.framework.util.StringUtils;

/**
 * 
 * @ClassName: SimpleSearchFormSupport
 * @Description: SearchForm支持类的就基本实现
 * @author 卢烁波
 * @date Apr 21, 2010 5:09:13 PM
 * 
 * @param <C>
 */
public class SimpleSearchFormSupport<C> implements ISearchFormSupport<C> {
	private static final String LIKE_REPLACE_MARK = "*";// 通配符匹配%搜索

	private static final String JOIN_PREFIX = "#{"; // 等于内连接

	private static final String LEFT_JOIN_PREFIX = "#L{";// 左连接

	private static final String INNER_JOIN_PREFIX = "#I{";// 内连接

	private static final String FULL_JOIN_PREFIX = "#F{";// 全连接


	private HibernateTemplate hibernateTemplate;
	private Class<C> persistentClass;
	private NameList<String, OrInfo> orMap;
	private List<OrInfo> defaultOrCondition;

	public Class<C> getPersistentClass() {
		return persistentClass;
	}

	public void setPersistentClass(Class<C> persistentClass) {
		this.persistentClass = persistentClass;
	}

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	/**
	 * @param <T>
	 * @param searchClass 进行查找的类
	 * @param session
	 * @param searchForm 条件类

	 * @param retClass 返回类型
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private <T> PagerResult<T> search(Class<?> searchClass, Session session,
			ISearchForm searchForm, Class<T> retClass) {
		if (searchForm == null) {
			return null;
		}
		if (searchClass == null) {
			searchClass = getPersistentClass();
		}
		OrInfo orInfo = null;
		orMap = new NameList<String, OrInfo>();
		defaultOrCondition = new ArrayList<OrInfo>();

		PagerResult<T> pagerResult = new PagerResult<T>();

		Pager pager = null;
		Class<? extends ISearchForm> clazz = searchForm.getClass();

		Criteria crit = session.createCriteria(searchClass, "o");

		ProjectionList projectList = null;

		/**
		 * 添加返回值信息,可以包括分组信息,如果分组后则不支持返回分页信息

		 */
		if (CollectionUtils.notEmpty(searchForm.getProjectionType())) {
			projectList = Projections.projectionList();
			for (ProjectionSearchType projection : searchForm
					.getProjectionType()) {
				projectList = addProjectionsSearchType(projectList, projection);
			}
			crit.setProjection(projectList);
		}

		/**
		 * 根据SearchForm中的定义的条件属性进行搜索

		 */
		List<Field> fields = ClassUtil.getAllDeclaredFields(clazz);
		PropertyCondition localpropertyCondition;
		List<PropertyCondition> localPropertyConditoins = new ArrayList<PropertyCondition>();
		for (Field f : fields) {
			/**
			 * 添加Field的条件

			 */
			String fieldName = f.getName();
			SearchProp searchProp = f.getAnnotation(SearchProp.class);
			SearchProps searchProps = f.getAnnotation(SearchProps.class);
			Object fieldValue = null;
			try {
				fieldValue = BeanUtils.getValue(searchForm, fieldName);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}

			if (searchProp != null) {
				addConditionBySearchProp(crit, f, searchProp, fieldValue);
			}
			if (searchProps != null
					&& CollectionUtils.notEmpty(searchProps.value())) {
				for (SearchProp p : searchProps.value()) {
					addConditionBySearchProp(crit, f, p, fieldValue);
				}
			}

			/**
			 * 添加field(属性)之间的条件,这个属性 = < > >= <= <> 另一个属性

			 */
			PropertySearchProp propertySearchProp = f
					.getAnnotation(PropertySearchProp.class);
			if (propertySearchProp != null) {
				if (!CommonUtil.isNullOrDefaultValue(fieldValue)) {
					localpropertyCondition = new PropertyCondition();
					String property1 = propertySearchProp.property1();
					String property2 = propertySearchProp.property2();
					String orKey = propertySearchProp.orKey();
					PropertySearchType type = propertySearchProp
							.propertySearchType();

					localpropertyCondition.setProperty1(property1);
					localpropertyCondition.setProperty2(property2);
					localpropertyCondition.setOrKey(orKey);
					localpropertyCondition.setPropertySearchType(type);

					orInfo = addPropertyCondition(crit, localpropertyCondition);
					if (orInfo != null) {
						orMap.putIntoList(orKey, orInfo);
					}
				}
			}
		}

		/**
		 * 根据动态定义的条件进行搜索
		 */
		Set<SearchCondition> conditions = searchForm.getConditions();
		if (conditions != null) {
			for (SearchCondition cond : conditions) {
				if (cond != null) {
					Object fieldValue = cond.getFieldValue();
					String fieldName = cond.getFieldName();

					String nullValue = cond.getNullValue() == null ? "" : cond
							.getNullValue();
					if (!CommonUtil.isNullOrDefaultValue(fieldValue, nullValue)) {
						orInfo = createSearchTypeToOrInfo(crit, fieldValue,
								cond.getSearchType(), fieldName);
						if (orInfo != null) {
							orMap.putIntoList(cond.getOrKey(), orInfo);
						}
					}
				}
			}
		}

		/**
		 * 添加属性间条件 这个属性 = < > >= <= <> 另一个属性

		 */
		List<PropertyCondition> propertyCondition = searchForm
				.getPropertyCondition();
		if (CollectionUtils.notEmpty(propertyCondition)) {
			localPropertyConditoins.addAll(propertyCondition);
		}
		for (PropertyCondition p : localPropertyConditoins) {
			orInfo = addPropertyCondition(crit, p);
			if (orInfo != null) {
				orMap.putIntoList(p.getOrKey(), orInfo);
			}
		}

		/**
		 * 将所有条件组合

		 */
		Map<String, List<OrInfo>> tmpMap = new HashMap<String, List<OrInfo>>();
		for (String k : orMap.getSource().keySet()) {
			List<OrInfo> lst = orMap.get(k);
			if (CollectionUtils.empty(lst)) {
				continue;
			}
			if (k.equals(SearchProp.DEFAULT_OR_KEY) || lst.size() == 1) {
				defaultOrCondition.addAll(lst);
			} else {
				tmpMap.put(k, lst);
			}
		}
		
		// OR连接条件
		Disjunction dis = null;
		for (String key : tmpMap.keySet()) {
			dis = Restrictions.disjunction();
			for (OrInfo info : tmpMap.get(key)) {
				dis.add(info.getCriterion());
			}
			tmpMap.get(key).get(0).crit.add(dis);
		}
		
		Set<SearchCondition> conditionsForAnd = searchForm.getConditionsForAnd();		
		if (conditionsForAnd != null) {
			NameList<String, OrInfo> orMap1 = new NameList<String, OrInfo>();
			for (SearchCondition cond : conditionsForAnd) {
				if (cond != null) {
					Object fieldValue = cond.getFieldValue();
					String fieldName = cond.getFieldName();

					String nullValue = cond.getNullValue() == null ? "" : cond
							.getNullValue();
					if (!CommonUtil.isNullOrDefaultValue(fieldValue, nullValue)) {
						orInfo = createSearchTypeToOrInfo(crit, fieldValue,
								cond.getSearchType(), fieldName);
						if (orInfo != null) {
							orMap1.putIntoList(cond.getOrKey(), orInfo);
						}
					}
				}
			}
			Map<String, List<OrInfo>> tmpMap1 = new HashMap<String, List<OrInfo>>();
			for (String k : orMap1.getSource().keySet()) {
				List<OrInfo> lst = orMap1.get(k);
				if (CollectionUtils.empty(lst)) {
					continue;
				}
				if (k.equals(SearchProp.DEFAULT_OR_KEY) || lst.size() == 1) {
					defaultOrCondition.addAll(lst);
				} else {
					tmpMap1.put(k, lst);
				}
			}
			Disjunction dis1 = Restrictions.disjunction();
			for (String key : tmpMap1.keySet()) {
				Conjunction con = Restrictions.conjunction();
				for (OrInfo info : tmpMap1.get(key)) {
					con.add(info.getCriterion());
				}
				dis1.add(con);				
			}
			crit.add(dis1);
		}
		
		// 添加默认的条件(所有都用AND连接)
		if (CollectionUtils.notEmpty(defaultOrCondition)) {
			for (OrInfo info : defaultOrCondition) {
				info.getCrit().add(info.getCriterion());
			}
		}
		/**
		 * 如果需要分页,则去得到分页的信息

		 */
		if (searchForm.isNeedPage()) {
			int maxResult = searchForm.getMaxResult();
			int pageSize = searchForm.getPageSize();

			// 用select count(*) 得到总记录数
			crit.setProjection(Projections.rowCount());
			int total = 0;
			crit.setMaxResults(1);
			Object resultCount = (Object) crit.uniqueResult();
			if (resultCount instanceof Number) {
				Number count = (Number) resultCount;
				total = count.intValue();
			}
			if (resultCount instanceof Object[]) {
				Object[] os = (Object[]) resultCount;
				if (CollectionUtils.notEmpty(os)) {
					total = ((Number) os[os.length - 1]).intValue();
				}
			}

			total = Math.min(total, maxResult);

			// 每页显示数

			pageSize = Math.min(pageSize, maxResult);

			// 设置分页器����

			pager = new Pager(total, pageSize, searchForm.getPage());

			// 最大显示数
			int max = Math.min(pageSize, maxResult);
			crit.setFirstResult(pager.getStart());

			if (max < ISearchForm.MAX_RESULT && max > 0) {
				crit.setMaxResults(max);
			}
		}

		crit.setProjection(projectList);

		/**
		 * 当设置crit.setProjection(null)后<BR>
		 * Criteria的ResultTransformer会变成PassThroughResultTransformer<BR>
		 * 所以就进行设置crit.setResultTransformer
		 */
		if (((CriteriaImpl) crit).getProjection() == null) {
			crit.setResultTransformer(Criteria.ROOT_ENTITY);
		}

		/**
		 * 设置排序条件
		 */
		List<NameValue<SearchOrder>> orderBys = searchForm.getOrderBys();
		if (orderBys != null && orderBys.size() > 0) {
			for (NameValue<SearchOrder> orderBy : orderBys) {
				if (orderBy.getValue() == SearchOrder.ASC) {
					crit.addOrder(Order.asc(orderBy.getName()));
				} else {
					crit.addOrder(Order.desc(orderBy.getName()));
				}
			}
		}

		pagerResult.setPager(pager);
		pagerResult.setResult((List<T>) crit.list());

		return pagerResult;

	}

	private void addConditionBySearchProp(Criteria crit, Field f,
			SearchProp searchProp, Object fieldValue) {
		OrInfo orInfo;
		String propFieldName;
		// 判断是否存在fieldName的值

		if (StringUtils.notEmpty(searchProp.fieldName())) {
			propFieldName = searchProp.fieldName();
		} else {
			propFieldName = f.getName();
		}

		if (!CommonUtil
				.isNullOrDefaultValue(fieldValue, searchProp.nullValue())) {
			orInfo = createSearchTypeToOrInfo(crit, fieldValue, searchProp
					.searchType(), propFieldName);
			if (orInfo != null) {
				orMap.putIntoList(searchProp.orKey(), orInfo);
			}
		}
	}

	/**
	 * 添加属性间的比较的条件
	 * 
	 * @param crit
	 * @param p
	 * @return
	 */
	private OrInfo addPropertyCondition(Criteria crit, PropertyCondition p) {
		OrInfo info = new OrInfo();
		info.setCrit(crit);
		switch (p.getPropertySearchType()) {
		case EQ:
			info.setCriterion(Restrictions.eqProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		case LT:
			info.setCriterion(Restrictions.ltProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		case LE:
			info.setCriterion(Restrictions.leProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		case NE:
			info.setCriterion(Restrictions.neProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		case GT:
			info.setCriterion(Restrictions.gtProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		case GE:
			info.setCriterion(Restrictions.geProperty(p.getProperty1(), p
					.getProperty2()));
			return info;
		}
		return null;
	}

	/**
	 * 添加返回值信息

	 * 
	 * @param list
	 * @param p
	 * @return
	 */
	private ProjectionList addProjectionsSearchType(ProjectionList list,
			ProjectionSearchType p) {
		switch (p.getProjectionType()) {
		case AVG:
			list.add(Projections.avg(p.getProjName()));
			break;
		case SUM:
			list.add(Projections.sum(p.getProjName()));
			break;
		case COUNT:
			list.add(Projections.count(p.getProjName()));
			break;
		case COUNT_DISTINCT:
			list.add(Projections.countDistinct(p.getProjName()));
			break;
		case MAX:
			list.add(Projections.max(p.getProjName()));
			break;
		case MIN:
			list.add(Projections.min(p.getProjName()));
			break;
		case GROUP_BY_PROP:
			list.add(Projections.groupProperty(p.getProjName()));
			break;
		case PROPERTIES:
			list.add(Projections.property(p.getProjName()));
			break;
		case PROPERTIES_DISTINCT:
			Projection proj = Projections.property(p.getProjName());
			list.add(Projections.distinct(proj));
			break;
		}

		return list;
	}

	private OrInfo createSearchTypeToOrInfo(Criteria crit, Object value,
			SearchType type, String fieldName) {
		OrInfo orInfo = null;
		if (fieldName == null || value == null) {
			return null;
		}

		/**
		 * 多表查询,如果已进行了多表搜索,则直接返回,不能再添加条件

		 */
		if (fieldName.startsWith(JOIN_PREFIX)
				|| fieldName.startsWith(FULL_JOIN_PREFIX)
				|| fieldName.startsWith(LEFT_JOIN_PREFIX)
				|| fieldName.startsWith(INNER_JOIN_PREFIX)) {
			orInfo = joinTableToOrInfo(crit, value, type, fieldName);
		} else {
			/**
			 * 直接添加搜索条件
			 */
			orInfo = this.addSearchConditionToOrInfo(crit, value, type,
					fieldName);
		}
		return orInfo;
	}

	private OrInfo joinTableToOrInfo(Criteria crit, Object value,
			SearchType type, String fieldName) {
		if (fieldName.startsWith(JOIN_PREFIX)
				|| fieldName.startsWith(FULL_JOIN_PREFIX)
				|| fieldName.startsWith(LEFT_JOIN_PREFIX)
				|| fieldName.startsWith(INNER_JOIN_PREFIX)) {

			String tmp = fieldName + "";
			/**
			 * 得到多表搜索的表的POJO
			 */
			String tableName = extractTableName(fieldName);

			/**
			 * 删除该表在fieldName定义的POJO名字
			 */
			fieldName = fieldName.substring(fieldName.indexOf("}.") + 2);

			Criteria subCrit = getSubCriteria(crit, tableName);
			if (subCrit == null) {
				if (tmp.startsWith(JOIN_PREFIX)
						|| tmp.startsWith(INNER_JOIN_PREFIX)) {
					int i = Criteria.INNER_JOIN;
					subCrit = crit.createCriteria(tableName, i);
				} else if (tmp.startsWith(FULL_JOIN_PREFIX)) {
					int f = Criteria.FULL_JOIN;
					subCrit = crit.createCriteria(tableName, f);
				} else if (tmp.startsWith(LEFT_JOIN_PREFIX)) {
					int l = Criteria.LEFT_JOIN;
					subCrit = crit.createCriteria(tableName, l);
				}
			}

			return this.joinTableToOrInfo(subCrit, value, type, fieldName);
		} else {
			return addSearchConditionToOrInfo(crit, value, type, fieldName);
		}
	}
	
//	private Criteria getCriteriaByFieldName(Criteria crit, String fieldName){
//		if (fieldName.startsWith(JOIN_PREFIX)){
//			/**
//			 * 删除该表在fieldName定义的POJO名字
//			 */
//			fieldName = fieldName.substring(fieldName.indexOf("}.") + 2);
//
//			return this.getCriteriaByFieldName(crit, fieldName);
//		} else {
//			return crit;
//		}
//	}

	private Criteria getSubCriteria(Criteria parent, String tableName) {
		Criteria tmpCrit = null;
		if (parent instanceof Subcriteria) {
			tmpCrit = ((Subcriteria) parent).getParent();
		} else {
			tmpCrit = parent;
		}
		Iterator<?> iterateSubcriteria = ((CriteriaImpl) tmpCrit)
				.iterateSubcriteria();
		while (iterateSubcriteria.hasNext()) {
			Subcriteria impl = (Subcriteria) iterateSubcriteria.next();
			String path = impl.getPath();
			if (path.equals(tableName)) {
				return impl;
			}
		}
		return null;
	}

	private OrInfo addSearchConditionToOrInfo(Criteria crit, Object value,
			SearchType type, String fieldName) {
		OrInfo info = new OrInfo();
		if (fieldName == null || value == null) {
			return null;
		}
		info.setCrit(crit);
		
		
		if(value instanceof String)
		{
			value = ((String)value).replace(LIKE_REPLACE_MARK, "%");
		}
		
		switch (type) {
		case LIKE_WITH_START:
			info.setCriterion(Restrictions.like(fieldName, (String) value,
					MatchMode.START));
			return info;

		case LIKE_WITH_END:
			info.setCriterion(Restrictions.like(fieldName, (String) value,
					MatchMode.END));
			return info;

		case LIKE_WITH_EXACT:
			info.setCriterion(Restrictions.like(fieldName, (String) value,
					MatchMode.EXACT));
			return info;

		case LIKE_WITH_ANYWHERE:
			info.setCriterion(Restrictions.like(fieldName, (String) value,
					MatchMode.ANYWHERE));
			return info;

		case ILIKE_WITH_START:
			info.setCriterion(Restrictions.ilike(fieldName, (String) value,
					MatchMode.START));
			return info;

		case ILIKE_WITH_EXACT:
			info.setCriterion(Restrictions.ilike(fieldName, (String) value,
					MatchMode.EXACT));
			return info;

		case ILIKE_WITH_END:
			info.setCriterion(Restrictions.ilike(fieldName, (String) value,
					MatchMode.END));
			return info;

		case ILIKE_WITH_ANYWHERE:
			info.setCriterion(Restrictions.ilike(fieldName, (String) value,
					MatchMode.ANYWHERE));
			return info;

		case EQ:
			info.setCriterion(Restrictions.eq(fieldName, value));
			return info;

		case NE:
			info.setCriterion(Restrictions.ne(fieldName, value));
			return info;

		case LT:
			info.setCriterion(Restrictions.lt(fieldName, value));
			return info;

		case LE:
			info.setCriterion(Restrictions.le(fieldName, value));
			return info;

		case GT:
			info.setCriterion(Restrictions.gt(fieldName, value));
			return info;

		case GE:
			info.setCriterion(Restrictions.ge(fieldName, value));
			return info;

		case IS_NULL:
			info.setCriterion(Restrictions.isNull(fieldName));
			return info;

		case IS_NOT_NULL:
			info.setCriterion(Restrictions.isNotNull(fieldName));
			return info;

		case NULL_OR_EQ:
			info.setCriterion(Restrictions.or(Restrictions.isNull(fieldName),
					Restrictions.eq(fieldName, value)));
			return info;

		case NULL_OR_EMPTY:
			info.setCriterion(Restrictions.or(Restrictions.isNull(fieldName),
					Restrictions.isEmpty(fieldName)));
			return info;

		case IN:
			if (value instanceof Collection) {
				Collection<?> v = (Collection<?>) value;
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.in(fieldName, v));
					return info;
				}
			}
			if (value instanceof Object[]) {
				Object[] v = (Object[]) value;
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.in(fieldName, v));
					return info;
				}
			}
			if (ClassUtils.isPrimitiveArray(value.getClass())) {
				// 基本类型数组转换成对象数组

				Object[] v = ObjectUtils.toObjectArray(value);
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.in(fieldName, v));
					return info;
				}
			}
			break;

		case NOT_IN:
			if (value instanceof Collection) {
				Collection<?> v = (Collection<?>) value;
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.not(Restrictions.in(
							fieldName, v)));
					return info;
				}
				return null;
			}
			if (value instanceof Object[]) {
				Object[] v = (Object[]) value;
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.not(Restrictions.in(
							fieldName, v)));
					return info;
				}
			}

			if (ClassUtils.isPrimitiveArray(value.getClass())) {
				// 基本类型数组转换成对象数组

				Object[] v = ObjectUtils.toObjectArray(value);
				if (CollectionUtils.notEmpty(v)) {
					info.setCriterion(Restrictions.not(Restrictions.in(
							fieldName, v)));
					return info;
				}
			}
		}
		return null;
	}

	/**
	 * 截取#{xxx}. 中xxx的字符串
	 * 
	 * @param fieldName
	 * @return
	 */
	private String extractTableName(String fieldName) {
		if (fieldName.startsWith(JOIN_PREFIX)) {
			return fieldName.substring(2, fieldName.indexOf("}."));
		}

		return fieldName.substring(3, fieldName.indexOf("}."));
	}

	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findBySearchForm(final Class<?> searchClass,
			final ISearchForm searchForm, final Class<T> retClazz) {
		return (PagerResult<T>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						return search(searchClass, session, searchForm,
								retClazz);
					}
				});
	}

	public PagerResult<C> findBySearchForm(ISearchForm searchForm) {
		return this.findBySearchForm(getPersistentClass(), searchForm,
				getPersistentClass());
	}

	public <T> PagerResult<T> findBySearchForm(Class<T> searchClass,
			ISearchForm searchForm) {
		return this.findBySearchForm(searchClass, searchForm, searchClass);
	}

	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findBySearchFormAndCast(ISearchForm searchForm,
			Class<T> retClazz) {
		return findBySearchFormAndCast(getPersistentClass(), searchForm,
				retClazz);
	}

	/**
	 * 保存Or条件信息
	 * 
	 * @author ronald
	 * @date 2008-3-11
	 */
	private static class OrInfo {
		private Criteria crit;
		private Criterion criterion;

		public Criteria getCrit() {
			return crit;
		}

		public void setCrit(Criteria crit) {
			this.crit = crit;
		}

		public Criterion getCriterion() {
			return criterion;
		}

		public void setCriterion(Criterion criterion) {
			this.criterion = criterion;
		}

	}

	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findBySearchFormAndCast(Class<?> searchClazz,
			ISearchForm searchForm, Class<T> retClazz) {
		if (retClazz == null || searchForm == null) {
			return null;
		}

		PagerResult<Object[]> pr = this.findBySearchForm(searchClazz,
				searchForm, Object[].class);

		return pr.cast(new ConstructorCaster(retClazz));
	}

}
